
{% extends "helios/templates/cryptobase.html" %}

{% block content %}
<script language="javascript">

$(document).ready(function() {
    $('#result_div').hide();
    $('#waiting_div').hide();
    $('#waiting_submit_div').hide();
    $('#done_div').hide();
    $('#error_div').hide();

    BigInt.setup(function() {
        ELECTION_JSON = {{election.toJSON|safe}};
        ELECTION_PK = ElGamal.PublicKey.fromJSONObject(ELECTION_JSON['public_key']);
        TALLY = HELIOS.Tally.fromJSONObject({{election.encrypted_tally.toJSON|safe}}, ELECTION_PK);
        $('#sk_section').show();
    });
});


function decrypt_and_prove_tally(tally, public_key, secret_key) {
    // we need to keep track of the values of g^{voter_num} for decryption
    var DISCRETE_LOGS = {};
    var CURRENT_EXP = 0;
    var CURRENT_RESULT = BigInt.ONE;
    DISCRETE_LOGS[CURRENT_RESULT.toString()] = CURRENT_EXP;

    // go through the num_tallied
    while (CURRENT_EXP < tally.num_tallied) {
      CURRENT_EXP += 1;
      CURRENT_RESULT = CURRENT_RESULT.multiply(public_key.g).mod(public_key.p);
      DISCRETE_LOGS[CURRENT_RESULT.toString()] = CURRENT_EXP;
    }

    // initialize the arrays
    var decryption_factors= [];
    var decryption_proofs= [];

    // decrypt the tallies
    $(tally.tally).each(function(q_num, q_tally) {
        decryption_factors[q_num] = [];
        decryption_proofs[q_num] = [];

        $(q_tally).each(function(choice_num, choice_tally) {
           var one_choice_result = secret_key.decryptionFactorAndProof(choice_tally, ElGamal.fiatshamir_challenge_generator);

           decryption_factors[q_num][choice_num] = one_choice_result.decryption_factor
           decryption_proofs[q_num][choice_num] = one_choice_result.decryption_proof;
        });
    });

    return {'decryption_factors': decryption_factors, 'decryption_proofs' : decryption_proofs};
}

function get_secret_key() {
  return ElGamal.SecretKey.fromJSONObject($.secureEvalJSON($('#sk_textarea').val()));
}

function do_tally() {
  $('#sk_section').hide();
  $('#waiting_div').show();

  var secret_key = get_secret_key();

  var factors_and_proof = decrypt_and_prove_tally(TALLY, ELECTION_PK, secret_key);

  // json'ify it
  var factors = factors_and_proof.decryption_factors
  var decryption_proofs = $(factors_and_proof.decryption_proofs).map(function(i, q_proof) {
      return $(q_proof).map(function(j, a_proof){
         return a_proof.toJSONObject();
      });
  });

  var factors_and_proofs = {'decryption_factors': factors, 'decryption_proofs': decryption_proofs};
  var factors_and_proofs_json = $.toJSON(factors_and_proofs);

  // clear stuff
  secret_key = null;
  $('#sk_textarea').val("");

  // display the result in a text area.
  $('#waiting_div').hide();

  $('#result_textarea').html(factors_and_proofs_json);
  $('#result_div').show();
  $('#first-step-success').show();
}

function submit_result() {
  $('#result_div').hide();
  $('#waiting_submit_div').show();

  var result = $('#result_textarea').val();

  // do the post
  $.ajax({
      type: 'POST',
      url: "./upload-decryption",
      data: {'factors_and_proofs': result},
      success: function(result) {
        $('#waiting_submit_div').hide();
        if (result != "FAILURE") {
          $('#done_div').show();
        } else {
          alert('verification failed, you probably used the wrong key.');
          reset();
        }
      },
      error: function(error) {
          $('#waiting_submit_div').hide();
          $('#error_div').show();
      }
  });
}

function skip_to_second_step() {
  $('#sk_section').hide();
  $('#result_div').show();
  $('#result_textarea').html('');
  $('#skip_to_second_step_instructions').hide();
}

function reset() {
  $('#result_div').hide();
  $('#skip_to_second_step_instructions').show();
  $('#sk_section').show();
  $('#result_textarea').html('');
  $('#first-step-success').hide();
}

</script>
  <h2 class="title">受托人 {{trustee.name}} &mdash; 解密结果 {{election.name}}</h2>

<p>
    <b>受托人:</b> <tt>{{trustee.email}}</tt><br />
    <b>公钥验证:</b> <tt>{{trustee.public_key_hash}}</tt><br />
    <b>完全加密的验证:</b> <tt>{{election.encrypted_tally_hash}}</tt>
</p>

    <p>
      已计算出您的选举的加密计数。<br />
      现在是计算和提交部分解密的时候了。
    </p>

    <p>
      这个过程分两步进行.<br /><br />
      <u>第一</u>, 密钥用于在浏览器内部进行解密计数操作, 不需要连接到网络设备.<br />
      如果你愿意，你可以在这一步将你的浏览器设置为离线.<br /><br />
      <u>第二</u>, 当你的解密因子已经被完全计数后，你需要将你的浏览器设置为接入网络，并且提交解密因子到服务器.<br />
      如果您愿意，您可以计算解密因子，将它们复制到剪贴板，重新启动浏览器，然后<br />
       跳到第二步，这样当你输入你的密钥时你的浏览器永远不会在线。
    </p>

  <div id="sk_section" style="display:none;">

      <form onsubmit="return false;">
          <h3>第一步: 输入密钥</h3>
          <textarea id="sk_textarea" cols="60" rows="5" style="height: 25em;"></textarea>
      </form>
      <p id="tally_section">
          <button onclick="do_tally();">生成部分解密密钥</button>
      </p>

      <p id="skip_to_second_step_instructions">
        <a href="javascript:skip_to_second_step();">跳转到第二步</a><br />
        (您必须已经计算出您的解密因子。)
      </p>
  </div>

  <div id="waiting_div">
      生成部分解密因子和证明...<br />
      <img src="/static/helios/loading.gif" />
  </div>

  <div id="waiting_submit_div">
      提交并检查您的解密因子和证明...<br />
      <img src="/static/helios/loading.gif" />
  </div>

  <div id="result_div">
      <h3>第二步: 上传部分解密密钥n</h3>
      <p id="first-step-success" style="display: none;">
          您的部分解密因子和证明已在下方生成<br />
           您的密钥已从内存中清除<br />
           准备好后，您可以将此结果提交给服务器
      </p>
      您的部分解密密钥:<br />
      <p>
          <textarea id="result_textarea" cols="60" rows="5" wrap="soft" style="height: 25em;"></textarea>
          <button onclick="submit_result();">将解密因子上传到服务器</button>
      </p>
      <p><a href="javascript:reset()">重置并且重新进行解密</a></p>
  </div>

  <div id="done_div">
      完成! <a href="{% url "election@view" election.uuid %}">返回选举</a>
  </div>

  <div id="error_div">
      您的密钥似乎不正确.
  </div>

  <div id="applet_div">
  </div>

{% endblock %}
